package Meta

import (
	"context"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"db2s/parDef"
	"db2s/ref"
	"reflect"
	"strings"
	"sync"
)

func (ma Meta) seqEr(drive string) (ter SeqEr, err error) {
	if ter, err = NewMetaSeq(drive); err != nil {
		err = ref.ErrAddPrintf("SeqEr", err)
		return
	}
	return
}
func (ma Meta) seqName() (meta any, err error) {
	var ter SeqEr
	if meta, err = parDef.CallMethod(ma.Drive, ma.Join, func(k int, v string) (result global.Return, err error) {
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		if result, err = ter.SeqName(parDef.CtxBackground(parDef.GeneralReadMethodParameter(ma.Parameter1[k], nil, ETL.StringGarth))); err != nil {
			return
		}
		return
	}); err != nil {
		err = ref.ErrAddPrintf("seqName", err)
		return
	}
	return
}
func SeqNameEq(parameter any, execFunc any) (result any, err error) {
	switch {
	case strings.EqualFold(fmt.Sprintf("%v", parameter), fmt.Sprintf("%v", execFunc)):
		return true, nil
	default:
		return false, nil
	}
}
func (ma Meta) seqExistence() (meta any, err error) {
	var ter SeqEr
	if meta, err = parDef.CallMethod(ma.Drive, ma.Join, func(k int, v string) (result global.Return, err error) {
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		if result, err = ter.SeqExistence(parDef.CtxBackground(parDef.GeneralReadMethodParameter(ma.Parameter1[k], SeqNameEq, ETL.String))); err != nil {
			return
		}
		return
	}); err != nil {
		err = ref.ErrAddPrintf("seqExistence", err)
		return
	}
	return
}

func (ma Meta) seqDrop() (meta any, err error) {
	var ter SeqEr
	if meta, err = parDef.CallMethod(ma.Drive, ma.Join, func(k int, v string) (result global.Return, err error) {
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		if result, err = ter.SeqDrop(parDef.CtxBackground(parDef.GeneralReadMethodParameter(ma.Parameter1[k], nil, ""))); err != nil {
			return
		}
		return
	}); err != nil {
		err = ref.ErrAddPrintf("tableDrop", err)
		return
	}
	return
}

type SeqDefinitionConvertS struct {
	Schema      string `json:"schema"`
	Name        string `json:"name"`
	MinValue    string `json:"minValue"`
	MaxValue    string `json:"maxValue"`
	IncrementBy string `json:"incrementBy"`
	CycleFlag   string `json:"cycleFlag"`
	OrderFlag   string `json:"orderFlag"`
	CacheSize   string `json:"cacheSize"`
	StartValue  string `json:"startValue"`
	Type        string `json:"type"`
	PrintInfo   string
}

func GetDbQueryOptions(parameter ETL.InstanceActiveS) ETL.InstanceActiveS {
	//return dataDispos.InstanceActiveS{
	//	DB:       parameter.Con,
	//	FixRows:  parameter.Options.FixRows,
	//	StopTime: parameter.Options.StopTime,
	//	SqlMode:  parameter.Options.SqlMode}
	return parameter
}
func SeqDefCreate(parameter any, _ any) (result any, err error) {
	var seq SeqDefinitionConvertS
	if parameter == nil {
		return
	}
	if err = global.MapSubToStructSubJsonName(parameter.(map[string]any), &seq); err != nil {
		return
	}
	result = seq
	return
}
func GetStructSubJsonNameValue(meta any, jsonName string) (result any, err error) {
	var mutex sync.RWMutex
	defer func() {
		defer func() {
			if r := recover(); r != nil {
				err = fmt.Errorf("panic: %v", r)
			}
			mutex.RUnlock()
		}()
	}()
	mutex.RLock()
	return getValueByJSONName(meta, jsonName)
}
func getValueByJSONName(meta interface{}, jsonName string) (interface{}, error) {
	// 获取meta的反射值
	metaValue := reflect.ValueOf(meta)
	metaType := reflect.TypeOf(meta)
	// 如果是指针，解引用
	if metaType.Kind() == reflect.Ptr {
		if metaValue.IsNil() {
			return nil, fmt.Errorf("meta is nil pointer")
		}
		metaValue = metaValue.Elem()
		metaType = metaType.Elem()
	}

	// 确保是结构体类型
	if metaType.Kind() != reflect.Struct {
		return nil, fmt.Errorf("meta is not a struct")
	}
	// 遍历结构体字段
	for i := 0; i < metaType.NumField(); i++ {
		field := metaType.Field(i)
		fieldValue := metaValue.Field(i)

		// 跳过不能访问的字段
		if !fieldValue.CanInterface() {
			continue
		}

		// 获取json标签
		jsonTag := field.Tag.Get("json")
		if jsonTag == "" {
			continue
		}
		// 解析json标签，获取第一个部分（字段名）
		tagName := strings.Split(jsonTag, ",")[0]
		// 如果匹配指定的jsonName
		if tagName == jsonName {
			// 对于引用类型，考虑返回副本以避免并发修改问题
			switch fieldValue.Kind() {
			case reflect.Slice:
				if fieldValue.Len() == 0 {
					return fieldValue.Interface(), nil
				}
				// 可以根据需要决定是否创建副本
				return fieldValue.Interface(), nil
			case reflect.Map:
				// map类型在并发读写时会有问题
				return fieldValue.Interface(), nil // 或者创建副本
			default:
				return fieldValue.Interface(), nil
			}
		}
	}
	return nil, fmt.Errorf("field with json name '%s' not found", jsonName)
}

func (ma Meta) seqDefinition() (meta any, err error) {
	var ter SeqEr
	if meta, err = parDef.CallMethod(ma.Drive, ma.Join, func(k int, v string) (result global.Return, err error) {
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		if result, err = ter.SeqDefinition(parDef.CtxBackground(parDef.GeneralReadMethodParameter(ma.Parameter1[k], SeqDefCreate, ETL.Map))); err != nil {
			return
		}
		return
	}); err != nil {
		err = ref.ErrAddPrintf("tableDrop", err)
		return
	}
	return
}
func (ma Meta) seqCreate() (meta any, err error) {
	var ter SeqEr
	var res []any
	for k, v := range ma.Drive {
		if len(ma.Drive) > 1 && joinExec(ma.Join, k) {
			res = append(res, nil)
			continue
		}
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		var result global.Return
		ma.Parameter1[k].GetJsonValue = GetStructSubJsonNameValue
		ctx := context.WithValue(context.Background(), "key", ma.Parameter1[k])
		if result, err = ter.SeqCreate(ctx); err != nil {
			return
		}
		res = append(res, result.Result)
	}
	meta = joinResult(ma.Join, res)
	return
}
func (ma Meta) seqPrint() (meta any, err error) {
	var ter SeqEr
	var res []any
	for k, v := range ma.Drive {
		if len(ma.Drive) > 1 && joinExec(ma.Join, k) {
			res = append(res, nil)
			continue
		}
		if ter, err = ma.seqEr(v); err != nil {
			return
		}
		var result global.Return
		ma.Parameter1[k].GetJsonValue = GetStructSubJsonNameValue
		ctx := context.WithValue(context.Background(), "key", ma.Parameter1[k])
		if result, err = ter.SeqPrint(ctx); err != nil {
			return
		}
		res = append(res, result.Result)
	}
	meta = joinResult(ma.Join, res)
	return
}
func (ma Meta) GetSeqMetaST() (result any, err error) {
	return ma.seqDefinition()
}
func (ma Meta) GetSeqCreateST() (result any, err error) {
	return ma.seqCreate()
}
func (ma Meta) GetSeqPrintST() (result any, err error) {
	return ma.seqPrint()
}
